// "Copyright [2021] <Copyright Shengkai Lin>"

// The topology of this network is shown as the ./oxc_cluster.png
// TODO(Lin) : The flexibility is still a problem

package cluster.networks;

import cluster.compound_modules.*;
import cluster.common.*;
import cluster.control.task_generator.*;
import cluster.control.ControlPlane;
import cluster.optical_devices.*;
import inet.networklayer.configurator.ipv4.*;
import inet.networklayer.ipv4.*;
import cluster.network_devices.*;

network HWOXCNetwork
{
    parameters:
        int numMachine = default(2);
        int numOxc = default(64);
        int numOpticalswitch8x64 = default(numMachine);  // Default it is the same as the machine num
        int numGpusperMachine = default(8);
        int numNvlink_port = default(4);
        int switch_delay = default(0);

    submodules:
        oxc[numOxc]: OpticalDevice{
            parameters:
                opticaldevice_type=0;
                numOptical_port=numMachine;
                my_index = index;
        }

        opticalswitch[numMachine] : OpticalDevice{
            parameters:
                opticaldevice_type=1;
                numOptical_port= numGpusperMachine + numOxc;
                my_index = index;
        }

        machine[numMachine] : MachineHW{
            parameters:
                numGpus = numGpusperMachine;
                numNvlink_port = numNvlink_port;
                my_index = index;
        }

        taskgenerater: TaskGenerater{
            parameters:
                maxnumGpus = numGpusperMachine * numMachine;
                modelsize = 100000;
        }

        control_plane: ControlPlane {
        }

        configurator: Ipv4NetworkConfigurator {
            parameters:
                @display("p=100,100;is=s");
                dumpAddresses = true;
                dumpTopology = true;
                dumpLinks = true;
                assignAddresses = false;
                 addSubnetRoutes = false;
                optimizeRoutes = false;
                networkType = 0;
        }

    connections allowunconnected:
        // Connect the data plane
        // Connect the machines first
        for i=0..numMachine-1, for j=0..numGpusperMachine-1 {
            machine[i].out_port[j] <-->Fiber<--> opticalswitch[i].optical_port[j];
        }
        for i=0..numMachine-1, for j=0..numOxc-1 {
            opticalswitch[i].optical_port[j+numGpusperMachine]<-->Fiber<-->oxc[j].optical_port[i];
        }


        // Connect the task generater and centralcontroller
        taskgenerater.central_controller_port --> control_plane.task_generater_port;

        // Connect the centralcontroller - machine
        for i=0..numMachine-1 {
            control_plane.machine_port++<-->ControlPlaneLink<-->machine[i].controller_port;
        }

        // Connect the switch - centralcontroller
        for i=0..numOxc-1 {
            control_plane.switch_port++ <-->ControlPlaneLink<--> oxc[i].controller_port;
        }
        for i=0..numOpticalswitch8x64-1 {
            control_plane.switch_port++ <-->ControlPlaneLink<--> opticalswitch[i].controller_port;
        }
}